<template>
  <div class="swiper">
    <!-- 主滑动区域 -->
    <div class="swiper-container">
      <slot></slot>
    </div>
    <!-- 滑动面板的点 -->
    <div class="swiper-indicator" v-if="indicatorDots && swiperNumber > 1">
      <div class="pointer"
        :style="{ 'background-color': showSwiperIndex === index ? indicatorActiveColor: indicatorColor }"
        @click="changeSwiperIndicatorHandler(index)"
        v-for="(num, index) in swiperNumber" :key="index"></div>
    </div>
    <!-- 左右滑动按钮 -->
    <div
      class="left-arrow iconfont icon-zuojiantou"
      :class="{ outside: outside ? 'outside' : '' }"
      @click="changeSwiperIndicatorByArrowHandler(showSwiperIndex - 1)"
      v-if="showArrow && swiperNumber > 1"></div>
    <div
      class="right-arrow iconfont icon-youjiantou1"
      :class="{ outside: outside ? 'outside' : '' }"
      @click="changeSwiperIndicatorByArrowHandler(showSwiperIndex + 1)"
      v-if="showArrow && swiperNumber > 1"></div>
  </div>
</template>

<script>
export default {
  props: {
    // 是否显示面板指示点
    indicatorDots: {
      type: Boolean,
      default: true
    },
    // 指示点颜色
    indicatorColor: {
      type: String,
      default: 'rgba(255, 255, 255, .3)'
    },
    // 当前选中的指示点颜色
    indicatorActiveColor: {
      type: String,
      default: '#FFFFFF'
    },
    // 是否自动切换
    autoplay: {
      type: Boolean,
      default: false
    },
    // 当前所在滑块的 index
    current: {
      type: Number,
      default: 0
    },
    // 自动切换时间间隔
    interval: {
      type: Number,
      default: 5000
    },
    // 滑动动画时长
    duration: {
      type: Number,
      default: 500
    },
    // 滑动方向是否为纵向
    vertical: {
      type: Boolean,
      default: false
    },
    // 是否显示左右箭头
    showArrow: {
      type: Boolean,
      default: true
    },
    // 是否超出显示
    outside: {
      type: Boolean,
      default: false
    }
  },

  data () {
    return {
      // banner的数量
      swiperNumber: 0,
      // 是否发送过
      isEmited: false,
      // 当前需要展示的banner图片
      showSwiperIndex: 0,
      // 上一次展示的banner图片
      lastShowSwiperIndex: -1,
      // 定时器
      timer: ''
    }
  },

  updated () {
    // swiperItem
    const swiperList = this.getSwiperItemList()
    // 设置数量
    this.swiperNumber = swiperList.length
    // 如果发送过，则不再请求接口
    if (this.isEmited) {
      return
    }
    this.changeSwiperIndicatorHandler(this.current, false)
  },

  created () {
    // 获取当前的展示的banner图片的索引
    this.$nextTick(() => {
      this.changeSwiperIndicatorHandler(this.current, false)
      this.swiperNumber = this.$slots.default ? this.$slots.default.length : 0
    })
    // 如果自动轮播，则开启定时器
    if (this.autoplay) {
      this.changeSwiperByInterval()
    }
  },

  methods: {
    /**
     * 获取轮播图列表，筛选出符合要求的
     */
    getSwiperItemList () {
      // 如果没有设置slot数据
      if (!this.$slots.default) {
        return []
      }
      return this.$slots.default.filter(item => !!item.componentInstance)
    },

    /**
     * 点击了下方的点，显示对应的banner图片
     * @param { Number }  index        当前需要展示的索引
     * @param { Boolean } isClearTimer 是否需要清除定时器
     */
    changeSwiperIndicatorHandler (index, isClearTimer = true) {
      // 如果当前需要暂停定时器，则先暂停定时器
      if (isClearTimer) {
        this.pauseTimer()
      }

      // 展示当次banner图片索引
      this.showSwiperIndex = index
      // 发送改变事件
      this.emitSwiperIndicatorChange()
    },

    /**
     * 发送改变事件
     */
    emitSwiperIndicatorChange () {
      // 获取轮播图列表
      const swiperList = this.getSwiperItemList()
      // 如果没有获取到slot
      if (swiperList.length === 0) {
        return
      }
      // 如果节点没有获取到
      if (!swiperList[this.showSwiperIndex] || !swiperList[this.showSwiperIndex].componentInstance) {
        return
      }
      // 将是否发送标志位置为true
      this.isEmited = true
      // 展示当前的tab
      swiperList[this.showSwiperIndex].componentInstance.showOrHideSwiper('in', this.showSwiperIndex > this.lastShowSwiperIndex)
      // 如果是第一次进来
      if (this.lastShowSwiperIndex < 0) {
        // 记录上一次展示的banner图片索引
        this.lastShowSwiperIndex = this.showSwiperIndex
        return
      }
      // 隐藏当前tab
      swiperList[this.lastShowSwiperIndex].componentInstance.showOrHideSwiper('out', this.showSwiperIndex > this.lastShowSwiperIndex)
      // 记录上一次展示的banner图片索引
      this.lastShowSwiperIndex = this.showSwiperIndex
    },

    /**
     * 通过左右箭头切换banner图片
     * @param { Number }  index        当前需要展示的索引
     * @param { Boolean } isClearTimer 是否需要清除定时器
     */
    changeSwiperIndicatorByArrowHandler (index, isClearTimer) {
      // 滑动的banner图片索引
      let swiperIndex = index

      // 如果当前小于0
      if (swiperIndex < 0) {
        swiperIndex = this.swiperNumber - 1
      } else if (swiperIndex > this.swiperNumber - 1) {
        swiperIndex = 0
      }

      // 开始滑动
      this.changeSwiperIndicatorHandler(swiperIndex, isClearTimer)
    },

    /**
     * 定时改变轮播图
     */
    changeSwiperByInterval () {
      this.timer = setInterval(() => {
        this.changeSwiperIndicatorByArrowHandler(this.showSwiperIndex + 1, false)
      }, this.interval)
    },

    /**
     * 暂停定时器
     */
    pauseTimer () {
      // 如果当前没有开启定时器，则不清除
      if (!this.autoplay) {
        return
      }
      // 如果轮播图长度小于1，则不轮播
      if (this.swiperNumber <= 1) {
        return
      }
      // 先清除定时器
      clearInterval(this.timer)
      // 动画执行完成后再开启定时器
      setTimeout(() => {
        this.changeSwiperByInterval()
      }, 500)
    }
  }
}
</script>

<style lang="less" scoped>
@import "./../../styles/variable";
@import "./../../styles/common";

.swiper {
  background: @write;
  width: 100%;
  height: 420px;
  position: relative;
  .swiper-container {
    width: 100%;
    height: 100%;
    overflow: hidden;
    position: relative;
  }
  .swiper-indicator {
    align-items: center;
    bottom: 16px;
    display: flex;
    position: absolute;
    width: 100%;
    height: 40px;
    justify-content: center;
    .pointer {
      .transition-fast;
      border-radius: 16px;
      cursor: pointer;
      width: 12px;
      height: 12px;
      margin: 0px 6px;
    }
  }
  .iconfont {
    background: @bg-light;
    border-radius: 40px;
    color: @font-color-light;
    cursor: pointer;
    font-size: 30px;
    width: 60px;
    line-height: 60px;
    top: calc(50% - 30px);
    position: absolute;
    text-align: center;
    &.left-arrow {
      left: 100px;
      &.outside {
        left: -70px;
      }
    }
    &.right-arrow {
      right: 100px;
      &.outside {
        right: -70px;
      }
    }
    &:hover {
      background: @bg-dark;
      color: @write;
    }
  }
}
</style>
